/*
 * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.ahoo.cosid.converter;

/**
 * 62-bit radix string ID converter that converts long IDs to compact string representations.
 *
 * <p>This converter uses a radix-62 character set consisting of:
 * <ul>
 *   <li>Digits: 0-9 (10 characters)</li>
 *   <li>Uppercase letters: A-Z (26 characters)</li>
 *   <li>Lowercase letters: a-z (26 characters)</li>
 * </ul>
 *
 * <p>The resulting string IDs are more compact than decimal representations,
 * using only 11 characters to represent the full range of long values.
 *
 * <p><strong>Important:</strong> If you use the string IDs generated by this
 * converter as database primary keys, you must configure the database to treat
 * the primary key column as case-sensitive, since the character set includes
 * both uppercase and lowercase letters.
 *
 * <p>Example conversions:
 * <ul>
 *   <li>12345 → "3d7"</li>
 *   <li>9876543210L → "1Zi6jE"</li>
 * </ul>
 *
 * @author ahoo wang
 */
public final class Radix62IdConverter extends RadixIdConverter {

    /**
     * The maximum character size for radix-62 encoded IDs.
     *
     * <p>This is the maximum number of characters needed to represent any
     * long value in radix-62 format, which is 11 characters.
     */
    public static final int MAX_CHAR_SIZE = 11;

    /**
     * The radix (base) used for conversion: 62 characters.
     *
     * <p>This represents the size of the character set used for encoding:
     * 10 digits + 26 uppercase letters + 26 lowercase letters = 62 characters.
     */
    public static final int RADIX = 62;

    /**
     * A shared instance without padding.
     *
     * <p>This instance converts IDs without padding the result to a fixed length,
     * producing variable-length string IDs.
     */
    public static final Radix62IdConverter INSTANCE = new Radix62IdConverter(false, MAX_CHAR_SIZE);

    /**
     * A shared instance with padding.
     *
     * <p>This instance converts IDs with padding to ensure all string IDs
     * have the same length (11 characters), which can be useful for sorting
     * and fixed-width storage requirements.
     */
    public static final Radix62IdConverter PAD_START = new Radix62IdConverter(true, MAX_CHAR_SIZE);

    /**
     * Get a Radix62IdConverter instance with the specified parameters.
     *
     * <p>This factory method returns an appropriate converter instance based on
     * the requested parameters. For common configurations, it returns shared
     * cached instances to improve performance and reduce memory usage.
     *
     * @param padStart Whether to pad the result with leading zeros
     * @param charSize The character size for padding (if enabled)
     * @return A Radix62IdConverter instance with the specified configuration
     */
    public static Radix62IdConverter of(boolean padStart, int charSize) {

        if (INSTANCE.isPadStart() == padStart && INSTANCE.getCharSize() == charSize) {
            return INSTANCE;
        }

        if (PAD_START.isPadStart() == padStart && PAD_START.getCharSize() == charSize) {
            return PAD_START;
        }

        return new Radix62IdConverter(padStart, charSize);
    }

    /**
     * Create a new Radix62IdConverter with the specified configuration.
     *
     * <p>This constructor creates a converter with custom padding and character
     * size settings. For most use cases, consider using the {@link #of(boolean, int)}
     * factory method which may return shared instances for better efficiency.
     *
     * @param padStart Whether to pad the result with leading zeros
     * @param charSize The character size for padding (if enabled)
     */
    public Radix62IdConverter(boolean padStart, int charSize) {
        super(padStart, charSize);
    }

    /**
     * Get the radix (base) used for conversion.
     *
     * @return The radix value (62)
     */
    @Override
    int getRadix() {
        return RADIX;
    }

    /**
     * Get the maximum character size for encoded IDs.
     *
     * @return The maximum character size (11)
     */
    @Override
    int getMaxCharSize() {
        return MAX_CHAR_SIZE;
    }

}
